package cn.com.sinux.spring.utils;

import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * Created by Administrator on 2015/8/26.
 */
public class QueryHelper {

    public static interface QueryWorker<T> {
        public List<T> query(List<String> ids);
    }

    public static interface PropertyReader<T, E> {
        public E read(T t);
    }

    public static interface MatchWorker<T> {
        public boolean match(T t);
    }

    public static <T> List<T> doFilter(List<T> ts, MatchWorker<T> matchWorker) {
        List<T> results = new LinkedList<T>();
        for (T t : ts) {
            if (matchWorker.match(t)) {
                results.add(t);
            }
        }
        return results;
    }

    public static <T> List<T> doRemove(List<T> ts, MatchWorker<T> matchWorker) {
        List<T> results = new LinkedList<T>();
        for (T t : ts) {
            if (!matchWorker.match(t)) {
                results.add(t);
            }
        }
        return results;
    }

    public static <T> boolean contains(List<T> ts, MatchWorker<T> matchWorker) {
        List<T> results = new LinkedList<T>();
        for (T t : ts) {
            if (matchWorker.match(t)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 去掉ID相同的值，返回还是LIST对象集合
     *
     * @param ts
     * @param ignalNull
     * @param propertyReader
     * @param <T>
     * @param <E>
     * @return
     */
    public static <T, E> List<T> doDistinctByProperty(List<T> ts, boolean ignalNull, PropertyReader<T, E> propertyReader) {
        Map<E, T> map = new HashMap<E, T>();
        for (T t : ts) {
            if (ignalNull && t == null) {
                LoggerFactory.getLogger(QueryHelper.class).debug("属性为null，被忽略了");
                continue;
            }
            E e = propertyReader.read(t);
            if (ignalNull && e == null) {
                LoggerFactory.getLogger(QueryHelper.class).debug("属性为null，被忽略了{}", t);
                continue;
            }
            map.put(e, t);
        }
        return new ArrayList<T>(map.values());
    }

    public static <T, E> List<E> doQueryProperties(List<T> ts, boolean ignalNull, PropertyReader<T, E> propertyReader) {
        List<E> ids = new LinkedList<E>();
        for (T t : ts) {
            if (ignalNull && t == null) {
                LoggerFactory.getLogger(QueryHelper.class).debug("属性为null，被忽略了");
                continue;
            }
            E e = propertyReader.read(t);
            if (ignalNull && e == null) {
                LoggerFactory.getLogger(QueryHelper.class).debug("属性为null，被忽略了{}", t);
                continue;
            }
            ids.add(e);
        }
        return ids;
    }

    public static <T, E> Set<E> doQuerySetProperties(List<T> ts, boolean ignalNull, PropertyReader<T, E> propertyReader) {
        Set<E> ids = new HashSet<E>();
        for (T t : ts) {
            if (ignalNull && t == null) {
                LoggerFactory.getLogger(QueryHelper.class).debug("属性为null，被忽略了");
                continue;
            }
            E e = propertyReader.read(t);
            if (ignalNull && e == null) {
                LoggerFactory.getLogger(QueryHelper.class).debug("属性为null，被忽略了{}", t);
                continue;
            }
            ids.add(e);
        }
        return ids;
    }

    public static <T> List<T> doQueryByIds(List<String> strings, QueryWorker<T> queryWorker) {
        if (ValidatorUtils.isArrayEmpty(strings)) {
            return Collections.emptyList();
        }
        int size = strings.size();
        if (size < 500) {
            return queryWorker.query(strings);
        }
        List<T> ts = new LinkedList<T>();
        for (int i = 0, l = size / 500; i < l; i++) {
            ts.addAll(queryWorker.query(strings.subList(i * 500, 500 * i + 499)));
        }
        int last = size % 500;
        if (last > 0) {
            ts.addAll(queryWorker.query(strings.subList(size - last, size - 1)));
        }
        return ts;
    }

    public static <T, E> List<T> doQuery(List<E> eList, PropertyReader<E, String> idPropertyReader, QueryWorker<T> queryWorker) {
        if (ValidatorUtils.isArrayEmpty(eList)) {
            return Collections.emptyList();
        }
        List<String> ids = doQueryProperties(eList, true, idPropertyReader);
        return doQueryByIds(ids, queryWorker);
    }
}
